package com.lovi.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lovi.clients.*;
import com.lovi.param.ProductHotParam;
import com.lovi.param.ProductIdsParam;
import com.lovi.param.ProductSaveParam;
import com.lovi.param.ProductSearchParam;
import com.lovi.pojo.Picture;
import com.lovi.pojo.Product;
import com.lovi.product.mapper.PictureMapper;
import com.lovi.product.mapper.ProductMapper;
import com.lovi.product.service.ProductService;
import com.lovi.to.OrderToProduct;
import com.lovi.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ProductServiceImpl extends ServiceImpl<ProductMapper,Product> implements ProductService {
    @Autowired
    private ProductMapper productMapper;
    //引入远程服务，启动类要配置好远程服务
    @Autowired
    private CategoryClient categoryClient;

    @Autowired
    private SearchClient searchClient;

    @Autowired
    private PictureMapper pictureMapper ;

    @Autowired
    private CartClient cartClient;

    @Autowired
    private OrderClient orderClient;

    @Autowired
    private CollectClient collectClient;



    /**
     * 根据类名查询首页商品信息
     * 需要调用分类服务，根据类名查询到类名id，再通过id来查询我们的商品列表
     * 还需要限制最多7条数据
     * @param categoryName
     * @return
     */
    @Cacheable(value = "list.product", key = "#categoryName" , cacheManager = "cacheManagerHour")
    @Override
    public R promo(String categoryName) {
        R r = categoryClient.byName(categoryName);
        //如果错误码一致就是失败
        if(r.getCode().equals(R.FAIL_CODE)){
//            log.info("ProductServiceImpl.promo 结果为->{}", "类名查询失败");
            return R.fail("类名查询失败");
        }
        //成功的情况
        // 类别服务中 data = category --- feign {json}  ----- product服务 LinkedHashMap jackson
        LinkedHashMap<String,Object> map = (LinkedHashMap<String, Object>) r.getData();
        //根据分类名我们可以得到队应的id
        Integer categoryId = (Integer) map.get("category_id");
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        wrapper.eq("category_id",categoryId);

        //要限制最多7个
        //新建分页对象
        IPage<Product> ipage = new Page<>(1,7);//一页最多7个
        IPage<Product> productIPage = productMapper.selectPage(ipage, wrapper);
        List<Product> records = productIPage.getRecords();
//        log.info("ProductServiceImpl.promo 结果为->{}", "ok");

        return R.ok("查询成功",records);
    }

    /**
     * 多类别热门商品查询 根据类别名称集合! 至多查询7条!
     *   1. 调用类别服务
     *   2. 类别集合id查询商品
     *   3. 结果集封装即可
     * @param productHotParam 类别名称集合
     * @return r
     */
    @Cacheable(value = "list.product",key = "#productHotParam.categoryName")
    @Override
    public R hots(ProductHotParam productHotParam) {

        R r = categoryClient.hots(productHotParam);

        if(r.getCode().equals(R.FAIL_CODE)){
            log.info("ProductServiceImpl.hots业务结束，结果:{}",r.getMsg());
            return r;
        }
        //？？为什么参数时productHotParam，，为什么返回时ids呢？
        List<Object> ids = (List<Object>) r.getData();

        //进行商品数据查询
        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("category_id",ids);
        queryWrapper.orderByDesc("product_sales");

        IPage<Product> page = new Page<>(1,7);

        page = productMapper.selectPage(page,queryWrapper);

        List<Product> records = page.getRecords();

        R ok = R.ok("多类别热门商品查询成功!", records);

        log.info("ProductServiceImpl.hots业务结束，结果:{}",ok);

        return ok;
    }

    /**
     * 查询类别商品集合
     *
     * @return
     */
    @Override
    public R clist() {
        R r = categoryClient.list();
        log.info("ProductServiceImpl.clist业务结束，结果:{}",r);

        return r;
    }

    /**
     * 类别商品查询 前端传递类别集合
     *
     * @param productIdsParam
     * @return
     */
    @Cacheable(value = "list.product",key = "#productIdsParam.categoryID+'-'+#productIdsParam.currentPage+'-'+#productIdsParam.pageSize")
    @Override
    public R byCategory(ProductIdsParam productIdsParam) {

        //1.拆分请求参数
        List<Integer> categoryIds = productIdsParam.getCategoryID();
        int currentPage = productIdsParam.getCurrentPage();
        int pageSize = productIdsParam.getPageSize();
        //2.请求条件封装
        QueryWrapper<Product> productQueryWrapper = new QueryWrapper<>();
        //不等于null跳过这里，等于就进入这里【方便复用】
        if (categoryIds != null && categoryIds.size() > 0){
            productQueryWrapper.in("category_id",categoryIds);
        }
        IPage<Product> page = new Page<>(currentPage,pageSize);
        //3.数据查询
        IPage<Product> iPage = productMapper.selectPage(page, productQueryWrapper);
        //4.结果封装
        List<Product> productList = iPage.getRecords();
        long total = iPage.getTotal();

        R ok = R.ok(null, productList, total);

//        log.info("ProductServiceImpl.byCategory业务结束，结果:{}",ok);
        return ok;
    }


    /**
     * 查询商品详情
     *
     * @param productID 商品id
     * @return
     */
    @Cacheable(value = "product",key = "#productID")
    @Override
    public R detail(Integer productID) {

        Product product = productMapper.selectById(productID);

        R ok = R.ok(product);

        log.info("ProductServiceImpl.detail业务结束，结果:{}",ok);

        return ok;
    }

    /**
     * 查询商品图片
     *
     * @param productID
     * @return
     */
    @Cacheable(value="picture",key = "#productID")
    @Override
    public Object pictures(Integer productID) {

        //参数封装
        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("product_id",productID);
        //数据库查询
        List<Picture> pictureList = pictureMapper.selectList(queryWrapper);
        //结果封装
        R r = R.ok(pictureList);

        log.info("ProductServiceImpl.pictures业务结束，结果:{}",r);

        return r;
    }

    /**
     * 查询全部商品信息
     *
     * @return
     */
    @Cacheable(value = "list.category",key = "#root.methodName",cacheManager = "cacheManagerDay")
    @Override
    public List<Product> list() {

        List<Product> products = productMapper.selectList(null);
//        log.info("ProductServiceImpl.list 结果为->{}", "查询全部商品信息成功！");
        return products;
    }


    /**
     * 关键字商品搜索
     *
     * @param productSearchParam
     * @return
     */
    @Override
    public Object search(ProductSearchParam productSearchParam) {

        R r = searchClient.search(productSearchParam);

        log.info("ProductServiceImpl.search业务结束，结果:{}",r);
        return r;
    }
    /**
     * 根据商品id集合查询商品信息
     *
     * @param productIds
     * @return
     */
    @Cacheable(value = "list.product",key = "#productIds")
    @Override
    public R ids(List<Integer> productIds) {

        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("product_id",productIds);

        List<Product> productList = productMapper.selectList(queryWrapper);

        R r = R.ok("类别信息查询成功!", productList);
        log.info("ProductServiceImpl.ids业务结束，结果:{}",r);
        return r;
    }
    /**
     * 根据商品id,查询商品id集合
     *
     * @param productIds
     * @return
     */
    @Override
    public List<Product> cartList(List<Integer> productIds) {

        QueryWrapper<Product> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("product_id",productIds);

        List<Product> productList = productMapper.selectList(queryWrapper);
        log.info("ProductServiceImpl.cartList业务结束，结果:{}",productList);
        return productList;
    }

    /**
     * 修改库存和增加销售量
     *
     * @param orderToProducts
     */
    @Override
    public void subNumber(List<OrderToProduct> orderToProducts) {

        //将集合转成map  productId orderToProduct
        Map<Integer, OrderToProduct> map = orderToProducts.stream().collect(Collectors.toMap(OrderToProduct::getProductId, v -> v));
        //获取商品的id集合
        Set<Integer> productIds = map.keySet();
        //查询集合对应的商品信息
        List<Product> productList = productMapper.selectBatchIds(productIds);
        //修改商品信息
        for (Product product : productList) {
            Integer num = map.get(product.getProductId()).getNum();
            product.setProductNum(product.getProductNum() - num); //减库存
            product.setProductSales(product.getProductSales()+num); //添加销售量
        }
        //批量更新
        this.updateBatchById(productList);
        log.info("ProductServiceImpl.subNumber业务结束，结果:库存和销售量的修改完毕");
    }

    /**
     * 通过类别id来查询有几条商品数据被那个类别引用了
     * @param categoryId
     * @return
     */
    @Override
    public Long adminCount(Integer categoryId) {
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        wrapper.eq("category_id",categoryId);
        Long count = productMapper.selectCount(wrapper);
        return count;
    }

    /**
     * 保存商品数据，关键是图片详情也得保存好呀，一张张图片详情还得做分割
     * 还得操作图片表，根据那个图片id啥的
     * @param productSaveParam
     * @return
     */
    @CacheEvict(value = "list.product",allEntries = true)
    @Transactional
    @Override
    public R adminProduct(ProductSaveParam productSaveParam) {
        //把商品数据存到数据库
        int i = productMapper.insert(productSaveParam);
        //如果失败了..
        if(i==0){
            return R.fail("商品数据保存失败");
        }
        log.info("ProductServiceImpl.adminProduct 结果为->{}", "商品数据保存成功");
        //数据库找到对应的product_id,然后对详情做处理
        QueryWrapper<Product> wrapper = new QueryWrapper<>();
        wrapper.eq("product_picture",productSaveParam.getProductPicture());
        Product product = productMapper.selectOne(wrapper);
        Integer productId = product.getProductId();

        //对详情图片做处理

        // 分割图片字符串为数组
        String[] pictureUrls = productSaveParam.getPictures().split("\\+");

        // 将图片URL数组转换为Picture对象列表
        List<Picture> picturesList = Arrays.stream(pictureUrls)
                .map(url -> {
                    Picture picture = new Picture();
                    picture.setProductId(productId); // 假设这是产品ID
                    picture.setProductPicture(url);
                    picture.setIntro("");
                    return picture;
                })
                .collect(Collectors.toList());

        // 批量插入图片表
        picturesList.forEach(picture -> pictureMapper.insert(picture));
        log.info("ProductServiceImpl.adminProduct 结果为->{}", "商品图片详情插入成功");
        //同步搜索服务的数据
        searchClient.saveOrUpdate(product);

        return R.ok("商品数据保存成功");
    }

    /**
     * 修改商品数据（不包括图片哦！）
     * 1.商品数据进行更新
     * 2.需要清空商品集合缓存和对应ID的缓存
     * 3.修改更新 es 搜索服务, es 直接覆盖更新即可
     * @param product
     * @return
     */
    @Override
    public R adminUpdate(Product product) {
        int i = productMapper.updateById(product);
        if(i>0){
            log.info("ProductServiceImpl.adminUpdate 结果为->{}", i);

            //同步搜索服务的数据
            R r = searchClient.saveOrUpdate(product);
            log.info("ProductServiceImpl.adminUpdate 结果为->{}", r);
            return R.ok("商品修改成功！");
        }


        return R.fail("商品修改失败！");
    }

    /**
     * 删除商品，需要考虑到如果商品被加入到购物车就不能删除
     * 1.删除商品数据，商品对应的图片详情
     * 2. 购物车，订单存在引用，不删除，收藏存在先清除收藏再删除
     * 3.需要清空商品集合缓存,清空特定ID的缓存
     * 4. 删除 es 搜索服务中的对应商品
     * @param productId
     * @return
     */
    @Caching(
            evict = {
                    @CacheEvict(value = "product.list",allEntries = true),
                    @CacheEvict(value = "product", key = "#productId")
            }
    )
    @Transactional
    @Override
    public R deleteProduct(Integer productId) {
        //先判断！如果存在引用就不删除
        R cartCheck = cartClient.check(productId);//购物车核验
        if(cartCheck.getCode().equals("004")){
            return cartCheck;
        }
        R ordercheck = orderClient.check(productId);//订单核验
        if(ordercheck.getCode().equals("004")){
            return ordercheck;
        }


        //删除商品数据和图片数据
        int i = productMapper.deleteById(productId);
        if(i==0){
            return R.fail("商品删除失败");
        }
        QueryWrapper<Picture> wrapper = new QueryWrapper<>();
        wrapper.eq("product_id",productId);
        pictureMapper.delete(wrapper);

        //清除收藏(反正不管有没有都会清除掉)
        collectClient.remove(productId);

        //同步es数据
        R remove = searchClient.remove(productId);
        log.info("ProductServiceImpl.deleteProduct 结果为->{}", remove);


        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return R.ok("刪除成功！");
    }


}
